package com.xunwulian.web.util;

import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayMonitorService;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayMonitorServiceImpl;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.service.impl.AlipayTradeWithHBServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.xunwulian.base.util.HttpUtil;
import com.xunwulian.base.util.MyLogUtil;
import com.xunwulian.web.bean.ZfbCallback;
import com.xunwulian.web.bean.ZfbEntity;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.UUID;

/**
 * Created by Administrator on 2017/2/22.
 */
public class ZfbUtil {

    private MyLogUtil myLogUtil = new MyLogUtil(ZfbUtil.class);

    // 支付宝当面付2.0服务
    private AlipayTradeService tradeService;

    // 支付宝当面付2.0服务（集成了交易保障接口逻辑）
    private AlipayTradeService tradeWithHBService;

    // 支付宝交易保障接口服务，供测试接口api使用，请先阅读readme.txt
    private AlipayMonitorService monitorService;

    public ZfbUtil(String confPath) {
        /**
         * 一定要在创建AlipayTradeService之前调用Configs.addNode()设置默认参数
         * Configs会读取classpath下的zfbinfo.properties文件配置信息，
         * 如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init(confPath);
        init();
    }

    public ZfbUtil() {
        Configs.init("zfbinfo.properties");
        init();
    }

    /**
     * 初始化操作
     */
    private void init() {
        /**
         * 使用Configs提供的默认参数 AlipayTradeService可以使用单例或者为静态成员对象，不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();

        // 支付宝当面付2.0服务（集成了交易保障接口逻辑）
        tradeWithHBService = new AlipayTradeWithHBServiceImpl.ClientBuilder().build();

        /**
         * 如果需要在程序中覆盖Configs提供的默认参数, 可以使用ClientBuilder类的setXXX方法修改默认参数
         * 否则使用代码中的默认设置
         */
        monitorService = new AlipayMonitorServiceImpl.ClientBuilder()
                .setGatewayUrl("http://mcloudmonitor.com/gateway.do").setCharset("GBK").setFormat("json").build();
    }

    /**
     * 支付返回二维码
     *
     * @param payEntity 支付实例
     * @return 二维码字符串
     */
    public String payForQRCode(ZfbEntity payEntity) {
        AlipayTradePrecreateRequestBuilder request = payEntity.createRequest();
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(request);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                myLogUtil.log("支付宝预下单成功: ");

                AlipayTradePrecreateResponse response = result.getResponse();
                dumpResponse(response);

                return response.getQrCode();

            case FAILED:
                myLogUtil.log("支付宝预下单失败!!!");
                return null;

            case UNKNOWN:
                myLogUtil.log("系统异常，预下单状态未知!!!");
                return null;

            default:
                myLogUtil.log("不支持的交易状态，交易返回异常!!!");
                return null;
        }
    }

    /**
     * 支付返回二维码文件的路径
     *
     * @param payEntity 支付实例
     * @param path      保存二维码文件的根路径
     * @return 二维码文件的路径
     */
    public String payForFile(ZfbEntity payEntity, String path) {
        path += UUID.randomUUID().toString();
        path += ".png";

        String qRCode = payForQRCode(payEntity);

        ZxingUtils.getQRCodeImge(qRCode, 256, path);

        myLogUtil.log("filePath:" + path);

        return path;
    }

    /**
     * 将回调的xml数据封装成对象
     *
     * @param req
     * @return
     * @throws IOException
     */
    public ZfbCallback parseCallback(HttpServletRequest req) throws IOException {
        InputStream inStream = req.getInputStream();
        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();

        byte[] buffer = new byte[1024];
        int len;

        while ((len = inStream.read(buffer)) != -1) {
            outSteam.write(buffer, 0, len);
        }

        outSteam.close();
        inStream.close();

        String json = new String(outSteam.toByteArray(), "utf8");

        System.out.println(json);

        Map<String, String> params = HttpUtil.paramsToMap(json, "utf8");

        return new ZfbCallback(params);
    }

    /**
     * 简单打印应答
     *
     * @param response 响应
     */
    private void dumpResponse(AlipayResponse response) {
        if (response != null) {
            myLogUtil.log(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                myLogUtil.log(String.format("subCode:%s, subMsg:%s", response.getSubCode(), response.getSubMsg()));
            }
            myLogUtil.log("body:" + response.getBody());
        }
    }
}
